home *** CD-ROM | disk | FTP | other *** search
/ Languguage OS 2 / Languguage OS II Version 10-94 (Knowledge Media)(1994).ISO / gnu / objcissu.lha / protocol-and-class < prev    next >
Internet Message Format  |  1993-03-01  |  22KB

  1. Date: Tue, 8 Sep 92 19:55:00 -0700
  2. From: Timothy J. Wood <bungi.cpac.washington.edu!bungi@bungi.cpac.washington.edu>
  3. To: <MKK2@psuvm.psu.edu>
  4. Subject: Re: Your mission, should you choose to accept it. . .
  5. Cc: gnu-objc@prep.ai.mit.edu
  6.  
  7.   It would be *really* nice to get gcc up to speed on the new
  8. features in the NeXT compiler before this project gets to far along,
  9. mainly the @protocol and @class directives.  For those of you not in
  10. the know,
  11.  
  12. @class Foo;
  13.  
  14.   is a forward declaration of a class, while
  15.  
  16. @protocol FooProtocol
  17. - fooMethod: fooArg;
  18. @end
  19.  
  20.   declares a protocol that any object can adopt:
  21.  
  22. #import "FooProtocol.h"
  23.  
  24. @interfrace FooClass : Object <FooProtocol, AnotherProtocol>
  25. ...
  26. @end
  27.  
  28.  
  29.   Then at run time, you can use Object's conformsTo: method to
  30. determine if a particular class declares support for a protocol (the
  31. "<...>" thing) and then respondsTo: to determine if it implements
  32. optional methods in the protocol.  Note that instance variables may
  33. not be declared as part of a protocol.
  34.   This is the clean alternative to C++'s multiple inheritence.
  35.  
  36.  
  37. Tim Wood
  38. The Omni Group
  39.  
  40. Date: Wed, 9 Sep 92 17:47:35 -0400
  41. From: athan@object.com (Andrew Athan)
  42. To: gnu-objc@prep.ai.mit.edu
  43. Subject: NeXT objc extentions (Was: Your mission, should you choose to accept it. . .)
  44. Cc: athan@uunet.uu.net
  45.  
  46.  
  47. [Previous discussion about @class, @protocol, etc.]
  48.  
  49. There are other issues besides whether or not the compiler code will
  50. become available from NeXT.  I personally feel that the @protocol
  51. extension has not been completely thought out by NeXT; I don't claim
  52. to know everything about it yet, nor do I claim to be doing everything
  53. right, but I feel certain pieces are missing/broken/not well thought
  54. out.
  55.  
  56. To elaborate: Though I can only guess, I'd say that NeXT put in
  57. @protocol largely as support for their distributed objects paradigm
  58. (so an NXProxy can say, conformsTo:@protocol(SOMETHING) instead of
  59. isKindOf:[Something class]) .. much like they added keywords like
  60. "out," "in," and "inout."  An @protocol (sometimes) builds a structure
  61. describing the methods; that structure is then tacked on to the Class
  62. object and can be used at runtime w/ distributed objects.  This is all
  63. fine, as far as distributed objects go.
  64.  
  65. As a language tool, I've begun to use @protocols in the code itself,
  66. much like a previous poster mentioned: to claim that some object
  67. conforms to some set of methods.  The first problem I ran into was
  68. that NeXT's @protocol support does not integrate class methods very
  69. well:
  70.  
  71. @protocol Controllers
  72. + someClassMethod;
  73. - someInstanceMethod;
  74. @end
  75.  
  76. Things work fine when I use Controllers to declare that a class or
  77. category compies:
  78.  
  79. @interface SomeControllerClass <Controllers>
  80. {}
  81. @end
  82.  
  83. The compiler correctly complains when I don't implement both
  84. someClassMethod and someInstanceMethod.  However, there is a problem
  85. in trying to (quietly) declare that some id conforms to the protocol
  86. because there is no way to tell the compiler if that id is pointing to
  87. a Class object or to some other object (this is especially sticky
  88. since Class objects are also subclasses of Object).
  89.  
  90. id <Controllers> x=[SomeControllerClass new];
  91. [x someClassMethod]            <--- Generates compiler warning that
  92.                     "x" does not respond to
  93.                     "someClassMethod"
  94.  
  95. This makes sense, since I never said "x is pointing to a class object."
  96.  
  97. Next, there is a problem with the way NeXT's compiler handles the
  98. @interface declaration above (IMHO).  Given that declaration, I am now
  99. forced to implement the entire Controllers protocol in the
  100. @implementation of SomeControllerClass.  I cannot (quietly) split it
  101. between various categories; *even if all the categories appear in the
  102. same .m!!*
  103.  
  104. E.g.,
  105. @implementation SomeConrollerClass
  106. - someInstanceMethod { return self; }
  107. @end
  108. @implementation SomeControllerClass(Category1)
  109. + someClassMethod;
  110. @end
  111.  
  112. yields compiler warnings.
  113.  
  114. An additional problem that I see with @protocol is the question of
  115. versioning.  Protocol checking is to some degree a compile-time event
  116. (and therefore versioning is not as important).  @protocol is,
  117. however, often used as a run-time tool: it is possible to ask an
  118. object if it conforms to a protocol.  Currently, I cannot attach a
  119. version number to a protocol.  Because of this, if someone writes and
  120. compiles an object given the Controllers protocol above, and I then at
  121. a later time write code which does:
  122.  
  123. if([someController conformsTo:@protocol(Controllers)])
  124.  
  125. in the meantime, having changed the Controllers protocol, I am in
  126. trouble.  This is partly because of NeXT's implementation of
  127. "conformsTo:" and partly because of the more fundamental versioning
  128. question.  NeXT only checks that "Controllers" is in the protocol list
  129. for "someController."  Nothing at all is to say that "someController"
  130. has the same concept of what the "Controllers" protocol *is* as I do.
  131. Whoever wrote "someController" might have ignored the compiler
  132. warnings and may in fact not have implemented *any* of the methods.
  133. This could be fixed by having a more robust strictConformsTo: method
  134. which would also verify "respondsTo:" status on all the methods in the
  135. protocol.  I still have a problem, however, if the semantics of the
  136. protocol have changed and I'd like to know what version of
  137. "Controllers" "someController" thinks it is responding to.
  138.  
  139. So, I think it is at least clear that there are "features" in the
  140. current implementation.  There are other ramifications as well, but I
  141. leave them to the floor...
  142.  
  143. Andrew Athan
  144.  
  145. Date: Thu, 10 Sep 1992 15:12:40 -0700
  146. From: Bruce Nilo <bruce@ictv.com>
  147. To: gnu-objc@prep.ai.mit.edu
  148. Subject: Re: Your mission, should you choose to accept it. . .
  149.  
  150. I think that NeXT's use of objective C should be just one factor in
  151. guiding the GNU objective C project. The fact of the matter is that
  152. NeXT's implementation of objective C can be improved upon and
  153. interface compatibility can be more or less maintained. Here are some
  154. things which I think can and should be improved.
  155.  
  156. PROTOCOL IMPROVEMENT: Previous postings have referred to NeXT
  157. protocols as lacking in certain respects. Part of the problem is in
  158. specifying exactly what problem they are suppose to solve. I do not
  159. think that distributed objects was the primary reason for their
  160. introduction. Seperating interface from implementation has been a
  161. topic in OOP for a long time. My personal opinion is that two
  162. compelling reasons for protocols is better compile time error
  163. reporting, and clearer more self documenting code. Runtime support,
  164. although useful, seems less of raison d'etre.
  165.  
  166. [moved ERROR HANDLING]
  167. [moved BETTER RUNTIME SUPPORT FOR MULTI-THREADED PROGRAMS]
  168. [moved GENERAL DATA STRUCTURES]
  169.  
  170. - Bruce D. Nilo
  171.  
  172. VP Software Systems
  173. ICTV
  174.  
  175. From: Steve_Naroff@next.com (Steve Naroff)
  176. Date: Fri, 11 Sep 92 12:14:25 -0700
  177. To: gnu-objc@prep.ai.mit.edu
  178. Subject: NeXT implementation of protocols
  179.  
  180.  
  181. I'm glad to see some folks are reading the documentation (it saves time)! Just to summarize, protocols definitely serve two purposes, they are:
  182.  
  183. (1) As a language feature, protocols provide a better way to declare pure, abstract data types (independent of the class hierarchy). We feel this encourages the reuse of design and provides better type checking (without compromising the flexibility of "id").
  184.  
  185. (2) As for distributed objects, protocols provide the runtime support to improve the efficiency and expressiveness of doing distributed programming, where the "class" may reside in another application. Note that we do not "force" you to use protocols, it is just slower and less descriptive than if you do.
  186.  
  187. Here are some brief comments on the headbutts that have been mentioned:
  188.  
  189. (1) Integration with class methods. The example given was was flawed, however...here is a slightly modified version:
  190.  
  191. @protocol Controllers
  192. + (void)someClassMethod;
  193. - (void)someInstanceMethod;
  194. @end
  195.  
  196. @interface SomeControllerClass : Object <Controllers>
  197. + (void)anotherClassMethod;
  198. @end
  199.  
  200. main()
  201. {
  202.     id <Controllers> buggy = [SomeControllerClass new];
  203.     id <Controllers> notBuggy = [SomeControllerClass class];
  204.  
  205.     [notBuggy someClassMethod]; // but produces bogus warning
  206.     [buggy someClassMethod]; // this was a flawed example
  207. }
  208.  
  209. The "real bug" is there is no way to declare "a class object for type SomeControllerClass", hence the bogus warning. This is where Objective-C's heritage of totally anonymous objects shines through! We were aware of this, it isn't hard to fix.
  210.  
  211. (2) Integration with categories. Category can adopt protocols just like classes. Here is a simple example that illustrates two possible organizations of a class.
  212.  
  213. @protocol Read
  214. - read:aStream;
  215. @end
  216.  
  217. @protocol Write
  218. - write:aStream;
  219. @end
  220.  
  221. @protocol Archiving <Read, Write>
  222. @end
  223.  
  224. @interface OneWayToOrganize : Object <Archiving>
  225. @end
  226. @implementation OneWayToOrganize
  227. - read:aStream { ... }
  228. - write:aStream { ... }
  229. @end
  230.  
  231. @interface AnotherWayToOrganize : Object
  232. @end
  233.  
  234. @interface AnotherWayToOrganize(ReadMethods) <Read>
  235. @end
  236. @implementation AnotherWayToOrganize(ReadMethods)
  237. - read:aStream { ... }
  238. @end
  239. @interface AnotherWayToOrganize(WriteMethods) <Write>
  240. @end
  241. @implementation AnotherWayToOrganize(WriteMethods)
  242. - write:aStream { ... }
  243. @end
  244.  
  245. I'm not sure this solves your problem, however I thought you might be interested in this capability. The suggestion that the compiler treat language elements (like classes/categories) differently, based on whether or not they happen to be in the same ".m" is flawed.
  246.  
  247. (3) Protocol versioning. We are well aware of this problem and didn't have time to come up with a solution we felt comfortable with. The problem is we don't do any type checking across module boundaries (either at linktime or runtime). Each ".o" module that references a protocol (via @protocol) gets a copy of the protocol object (the linker does not unique them) used by the runtime system for that module. Since protocols are "abstract", they have no obvious "home" (i.e. place to generate them, like there is for classes)...as a result, attaching a version # is tricky. I'm glad there are other folks thinking about solutions to this problem.
  248.  
  249. In summary, I am glad to see support for improving the NeXT implementation of protocols and hope some of this info helps. We are using protocols quite extensively within NeXT and have some ideas for future enhancements (I will keep you posted).
  250.  
  251. bye, snaroff.
  252.  
  253. Date: Fri, 11 Sep 92 15:28:07 -0400
  254. From: athan@object.com (Andrew Athan)
  255. To: gnu-objc@prep.ai.mit.edu
  256. Subject: Re: NeXT implementation of protocols
  257.  
  258. In response to my having complained about spurious compiler warnings when some protocol is implemented in whole in one .m file, but the various methods in the protocol are actually split between multiple categories in that .m,  Steve_Naroff@NeXT.com writes:
  259. >(2) Integration with categories. Category can adopt protocols just like classes. Here is a
  260. >simple example that illustrates two possible organizations of a class.
  261.  
  262. and gives an example illustrating the ability to declare that a *category* responds to some protocol:
  263.  
  264. @protocol Read
  265. - read:aStream;
  266. @end
  267.  
  268. @protocol Write
  269. - write:aStream;
  270. @end
  271.  
  272. @protocol Archiving <Read, Write>
  273. @end
  274.  
  275. @interface OneWayToOrganize : Object <Archiving>
  276. @end
  277. @implementation OneWayToOrganize
  278. - read:aStream { ... }
  279. - write:aStream { ... }
  280. @end
  281.  
  282. @interface AnotherWayToOrganize : Object
  283. @end
  284.  
  285. @interface AnotherWayToOrganize(ReadMethods) <Read>
  286. @end
  287. @implementation AnotherWayToOrganize(ReadMethods)
  288. - read:aStream { ... }
  289. @end
  290. @interface AnotherWayToOrganize(WriteMethods) <Write>
  291. @end
  292. @implementation AnotherWayToOrganize(WriteMethods)
  293. - write:aStream { ... }
  294. @end
  295.  
  296.  
  297.  
  298.  
  299. Stated as I have in the first sentence of this email, Steve's example does not solve the problem.  It is useful when the protocol you are trying to implement happens to be "decomposable."  It has the disadvantage that "AnotherWayToOrganize" no longer responds to the <Archiving> protocol, only to the <Read> and to the <Write> protocols.  I am under the impression that asking conformsTo:@protocol(Archiving) to the object will then yield NO (am I right Steve?)
  300.  
  301. I think the compiler should not issue warnings regarding non-conformance to protocols until the entire .m file has been processed.
  302.  
  303. Andrew Athan
  304.  
  305. From: Steve_Naroff@next.com (Steve Naroff)
  306. Date: Sun, 13 Sep 92 08:28:35 -0700
  307. To: athan@object.com (Andrew Athan)
  308. Subject: Re: NeXT implementation of protocols
  309. Cc: gnu-objc@prep.ai.mit.edu
  310.  
  311.  
  312. > I am under the impression that asking conformsTo:@protocol(Archiving) to the object will then yield NO (am I right Steve?)
  313.  
  314. You are right...my original email said "I'm not sure this solves your problem, however I thought you might be interested in this capability." I guess you weren't.
  315.  
  316. > I think the compiler should not issue warnings regarding non-conformance to protocols until the entire .m file has been processed.
  317.  
  318. I'm not sure I understand your suggestion. In general, I don't like "file boundaries" to effect language semantics. The unit of modularity in Objective-C is the class, category, protocol, etc...what files these entities reside in is irrelevant to the compiler. Context dependencies make it hard to reorganize various aspects of your program. I'm not saying your desire to implement a protocol across class/category boundaries is superfluous, I just don't like relying on file boundaries to implement it.
  319.  
  320. snaroff.
  321.  
  322. Date: Mon, 14 Sep 92 10:35:38 CDT
  323. From: billb@jupiter.fnbc.com
  324. To: gnu-objc@prep.ai.mit.edu
  325. Subject: Protocols, Reflection
  326.  
  327. At first blush the idea of versioning protocols seemed appropriate.  Now, after thinking more about protocols I believe that perhaps I would like a better implementation, to wit:  Why are protocols checked by name and not by _value_?  This is yet another barrier between us and code reuse.  When I write a class I cannot possibly imagine all of the protocols that that class responds to (combination of all methods it implements), yet that class _does_ respond to any protocol which specifies some subset of that class' methods.  Please, someone, correct me if I am wrong about the way that protocol conformance is determined at runtime.  Protocols should _eliminate_ the version dependence of our code!  Protocols should be interfaces.  If an object has the same interface, then I don't care what version it is.  Of course this may be naive of me.
  328.  
  329. Also, while I have your ear, wouldn't it be nice to have some more powerful reflective facilities in the language.  Maybe I just need to dig deeper into Obj-C++, but I haven't seen the kind of facilities that I really need.  If such changes are _off_limits_ for this projects then just stop reading _now_.
  330.  
  331. An example of a useful reflective capability would be the ability to override an Object method that would automatically get invoked every time any method is entered; I would also like a similar method for method exit.  I would like to be able to override these methods for a given class, and additionally for particular instances of a class.
  332.  
  333. see:
  334. [Graube 89] N. Graube, "Metaclass Compatibility" OOPSLA '89 Conference Proceedings, Special Issue of Sigplan Notices, Vol. 24 No. 10, October 1989.
  335.  
  336. [Ferber 89] J. Ferber, "Computational Reflection in Class based Object Oriented Languages" OOPSLA '89 Conference Proceedings, Special Issue of Sigplan Notices, Vol. 24 No. 10, October 1989.
  337.  
  338. [Foote & Johnson 89] B. Foote and R.E. Johnson, "Reflective Facilities in Smalltalk-80" OOPSLA '89 Conference Proceedings, Special Issue of Sigplan Notices, Vol. 24 No. 10, October 1989.
  339.  
  340. (gimme a break -- I _do_ _to_ have more than one book!)
  341. That's all.
  342.  
  343. Bill
  344.  
  345. Date: Tue, 15 Sep 92 11:07:21 CDT
  346. From: billb@jupiter.fnbc.com
  347. To: gnu-objc@prep.ai.mit.edu
  348. Subject: Re: Protocols, Reflection (forgive my rambling)
  349.  
  350. > billb@fnbc.com writes:
  351. > > <<stuff omitted>>
  352. > > Please, someone, correct me if I am wrong about the way
  353. > > that protocol conformance is determined at runtime. 
  354. > > Protocols should _eliminate_ the version dependence of
  355. > > our code!  Protocols should be interfaces.  If an object
  356. > > has the  same interface, then I don't care what version it
  357. > > is.  Of course this may be naive of me. 
  358. > >  <<stuff omitted>>
  359. >
  360. > athan@object.com (Andrew Athan) writes:
  361. > The question is, what assumption do we want to make?  If I
  362. > respond to someMethod, shall I assume that its semantics
  363. > will  always remain the same?  If so, then what you say is
  364. > true.  However, if between version1 of someProtocol and
  365. > version2,  the method setStringValue: starting doing
  366. > something differently (e.g., updating a database as
  367. > well as the object itself)  then I could conceivably need
  368. > to know that version I'm talking to.
  369. >
  370. > An additional point is:  Is what I've described a question
  371. > of protocol or object versioning?  Does anyone have
  372. > arguments  pro/con this?
  373.  
  374. I see your point.  I didn't really understand what was bugging me until I read your response.  So, do we add semantic information to protocols?!?  No, because that puts us right back where we started -- if we could express the semantics in the protocol then we would already have an implementation.
  375.  
  376. Your point brings up the following problem:  we are talking about two distinct entities here.  One is already implemented by the Obj-C protocol.  The other is a semantic specification (currently in the implementors head) of the semantics of those methods.  Version numbers on protocols really have nothing to do w/ Obj-C protocols, but everything to do w/ identifying some (currently undocumented) semantic description of objects.  It would be just as valid to change the protocol name each time the protocol was rev'd (add a vers count to the end of the name if you like) as it would be to have a seperate version number.  Its all just a naming problem -- just like so many of our problems.
  377.  
  378. [[billb putPropellorOnHead] mountSoapbox]
  379. IMHO we should do away w/ our one-dimensional programming paradigms in which we use names to refer to _things_, and instead actually specify to those _things_ directly, as we program.  There should be no `symbol table' in a compiler.  I should be able to annotate (or not) any entity in my program.  How long am I going to have to suffer the lowest common denominator (vi) for program entry.  We all have GUI's now don't we?
  380.  
  381. Bill
  382.  
  383. From: Charles Lloyd <wiltel!clloyd@uunet.uu.net>
  384. Date: Tue, 15 Sep 92 13:53:40 -0500
  385. To: uunet!prep.ai.mit.edu!gnu-objc@uunet.uu.net
  386. Subject: Re: Protocols, Reflection...objc_msgSend()
  387.  
  388. RE: Overriding objc_msgSend().
  389.  
  390. I want to strongly second the motion that Kim Christensen has suggested!  The particular problem solved by this solution is not as important as the fact that we need the ability to override objc_msgSend().  I was thinking of sending an almost identical suggestion myself, but Kim has saved me the trouble (as well as verified my thinking).
  391.  
  392. We have encountered many problems here at WilTel which could have been easily handled if we had the ability to "override" the objc_msgSend() function.  For example, we have an approach to persistant object storage which is far more complicated (and inefficient) than it need be if we had the ability to augment obj_msgSend().  Kim's suggestion is an excellent one which can handle numerous problems.  Of course, there may be hidden problems which I'm not seeing, but something like this is sorely needed.
  393.  
  394. Charles Lloyd.
  395.  
  396. ps:  I hope this discussion is considered to be germane to the project.  This gnu effort has an opportunity to correct some of the deficiencies in the NeXT implementation and I think its wise to get these ideas heard early in this forum.
  397.  
  398.  
  399. Date: Tue, 15 Sep 92 08:10:31 +0100
  400. From: Kim Harding Christensen <uunet!dannug.dk!khc>
  401. To: gnu-objc@prep.ai.mit.edu
  402. Subject: Re:Protocols, Reflection
  403.  
  404.  
  405. <stuff deleted>
  406.  
  407. We could do all these things (and a lot more) if the messenger function is implemented as a pointer to a function:
  408.  
  409. id objc_msgSend(id self, SEL theSelector, ...)
  410. {
  411.     ....
  412. }
  413.  
  414. theMessenger = objc_msgSend;
  415.  
  416. <stuff deleted>
  417.  
  418. Date: Tue, 15 Sep 92 08:10:31 +0100
  419. From: Kim Harding Christensen <khc@dannug.dk>
  420. To: gnu-objc@prep.ai.mit.edu
  421. Subject: Re:Protocols, Reflection
  422.  
  423. Bill writes:
  424.  
  425. > .... Also, while I have your ear, wouldn't it be nice to have
  426. > some more powerful reflective facilities in the
  427. > language.  Maybe I just need to dig deeper into Obj-C++,
  428. > but I haven't seen the kind of facilities that I really
  429. > need.  If such changes are _off_limits_ for this projects
  430. > then just stop reading _now_.
  431.  
  432. > An example of a useful
  433. > reflective capability would be the ability to override
  434. > an Object method that would automatically get invoked
  435. > every time any method is entered; I would also like a
  436. > similar method for method exit.  I would like to be able to
  437. > override these methods for a given class, and
  438. > additionally for particular instances of a class.
  439. >
  440.  
  441. We could do all these things (and a lot more) if the messenger function is implemented as a pointer to a function:
  442.  
  443. id objc_msgSend(id self, SEL theSelector, ...)
  444. {
  445.     ....
  446. }
  447.  
  448. theMessenger = objc_msgSend;
  449.  
  450. To implement pre- and post-condition we could write something like:
  451.  
  452. id preAndPostMessenger(id self, SEL theSelector, ...)
  453. {
  454.     String *preSel = [[String newSTR:"pre_"]
  455.                 catSTR:sel_getName(theSelector)];
  456.     String *postSel = [[String newSTR:"post_"]
  457.                 catSTR:sel_getName(theSelector)];
  458.     id retval;
  459.     
  460.     if ([self respondsTo:sel_getUid([preSel str])])
  461.     {
  462.         if (!(BOOL)objc_msgSend(self,
  463.                 sel_getUid([preSel str]), ...))
  464.         {
  465.             return objc_msgSend(self, @selector(error:),
  466.                 "pre condition failed");
  467.         }
  468.     }
  469.     retval = objc_msgSend(self, theSelector, ...);
  470.     if ([self respondsTo:sel_getUid([postSel str])])
  471.     {
  472.         if (!(BOOL)objc_msgSend(self,
  473.                 sel_getUid([postSel str]), ...))
  474.         {
  475.             return objc_msgSend(self, @selector(error:),
  476.                 "post condition failed");
  477.         }
  478.     }
  479.     return retval;
  480. }
  481.  
  482. ...
  483.  
  484. main()
  485. {
  486.     theMessenger = preAndPostMessenger;
  487.     ...
  488. }
  489.  
  490. /kim
  491.  
  492.